﻿//---------------------------------------------------------------------
// <copyright file="PhpClientQueryVerifier.cs" company="Microsoft">
//      Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information.
// </copyright>
//---------------------------------------------------------------------

namespace Microsoft.Test.Taupo.Astoria.Php
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.IO;
    using System.Linq;
    using System.Text;
    using Microsoft.Test.Taupo.Astoria.Contracts;
    using Microsoft.Test.Taupo.Astoria.Php;
    using Microsoft.Test.Taupo.Common;
    using Microsoft.Test.Taupo.Contracts;
    using Microsoft.Test.Taupo.Query.Contracts;

    /// <summary>
    /// Builds and verifies queries using PHP client library
    /// </summary>
    [ImplementationName(typeof(IQueryVerifier), "Php")]
    public sealed class PhpClientQueryVerifier : IQueryVerifier, IDisposable
    {
        /// <summary>
        /// Gets or sets the current service descriptor
        /// </summary>
        [InjectDependency(IsRequired = true)]
        public IAstoriaServiceDescriptor Service { get; set; }

        /// <summary>
        /// Gets or sets the Code Generator to be used
        /// </summary>
        [InjectDependency(IsRequired = true)]
        public INonClrCodeGenerator CodeGenerator { get; set; }

        /// <summary>
        /// Gets or sets the Code Executor to be used
        /// </summary>
        [InjectDependency(IsRequired = true)]
        public IPhpCodeExecutor CodeExecutor { get; set; }

        /// <summary>
        /// Gets or sets the name of the generated Php file for the Data Service
        /// </summary>
        public string DataServicePhpFileName { get; set; }

        /// <summary>
        /// Gets or sets the logger used to print diagnostic messages.
        /// </summary>
        /// <value>The logger.</value>
        [InjectDependency]
        public Logger Logger { get; set; }

        /// <summary>
        /// Gets or sets the working directory for the php client library
        /// </summary>
        [InjectTestParameter("PhpWorkingDirectory", DefaultValueDescription = "C:\\PHPLib\\odataphp")]
        public string PhpWorkingDirectory { get; set; }

        /// <summary>
        /// Verifies the query generated by the PHPCodeGenerator
        /// </summary>
        /// <param name="expression">The expression used to verify the query</param>
        public void Verify(QueryExpression expression)
        {
            ExceptionUtilities.CheckArgumentNotNull(expression, "expression");
            ExceptionUtilities.CheckAllRequiredDependencies(this);

            if (this.DataServicePhpFileName == null)
            {
                this.DataServicePhpFileName = this.PhpWorkingDirectory + "\\" + this.Service.ConceptualModel.EntityContainers.First().Name + ".php";
            }

            if (!File.Exists(this.DataServicePhpFileName))
            {
                string commandToGenerateConatinerClass = string.Format(CultureInfo.InvariantCulture, "{0}{1} /ups=no", "PHPDataSvcUtil.php /uri=", this.Service.ServiceUri.AbsoluteUri);
                this.CodeExecutor.ExecuteCode(commandToGenerateConatinerClass);
            }
            
            var fileName = string.Format(CultureInfo.InvariantCulture, "{0}{1}.php", DateTime.Now.Day.ToString(CultureInfo.InvariantCulture), DateTime.Now.TimeOfDay.ToString().Replace(':', '.'));
            string phpCode = this.CodeGenerator.GenerateCode(expression);
            File.WriteAllText(string.Format(CultureInfo.InvariantCulture, "{0}\\{1}", this.PhpWorkingDirectory, fileName), phpCode);
            string result = this.CodeExecutor.ExecuteCode(fileName);
            if (!result.Equals("Passed"))
            {
                Logger.WriteLine(LogLevel.Verbose, CultureInfo.InvariantCulture, "Execution of the Php query failed");
                throw new DataComparisonException(string.Format(CultureInfo.InvariantCulture, "The Php query failed\n Generated Php Code :\n{0}\n Error : {1}", phpCode, result));
            }
        }

        /// <summary>
        /// Deletes the generated php file generated for the Data Service
        /// </summary>
        public void Dispose()
        {
            File.Delete(this.DataServicePhpFileName);
        }
    }
}
